package edu.uclmgmu.bacteriosec.aspects.common;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
 
/**
 * Abstract logging aspect for producing indented logging. Override the
 * <code>loggingOperations</code> pointcut in order to provide the joinpoints
 * where you would like the logging to be applied. Also override the methods
 * <code>beforeLog</code> and <code>afterLog</code> to provide the actual
 * logging statements. The current indentation string will be provided to these
 * methods, along with an instance of <code>JoinPoint</code>.
 *
 * @author Ulrik Sandberg
 */
privileged abstract aspect IndentedLogging {
    Log log = LogFactory.getLog("trace");
 
    /**
     * The current number of indentation levels.
     */
    protected int indentationlevel = 0;
 
    /**
     * Override and provide pointcut to log.
     */
    protected abstract pointcut loggingOperations();
 
    /**
     * Override and provide the actual logging statement for when the logged
     * method is entered.
     *
     * @param indent
     *            The string of spaces that provides the current indentation.
     * @param joinPoint
     *            Information about the current joinpoint.
     */
    protected abstract void beforeLog(String indent, JoinPoint joinPoint);
 
    /**
     * Override and provide the actual logging statement for when the logged
     * method is exited.
     *
     * @param indent
     *            The string of spaces that provides the current indentation.
     * @param joinPoint
     *            Information about the current joinpoint.
     */
    protected abstract void afterLog(String indent, JoinPoint joinPoint);
 
    Object around(): loggingOperations() {
        StringBuffer sb = new StringBuffer();
        if (log.isInfoEnabled()) {
            indentationlevel++;
            for (int i = 0, spaces = indentationlevel * 2; i<spaces; i++) {
                sb.append(" ");
            }
            beforeLog(sb.toString(), thisJoinPoint);
        }
        Object result;
        try {
            result = proceed();
        } finally {
            if (log.isInfoEnabled()) {
                afterLog(sb.toString(), thisJoinPoint);
                indentationlevel--;
            }
        }
        return result;
    }
}